<?php

namespace common\models;

use common\Service\RedisService;
use Yii;
use common\models\Common;
use yii\data\ActiveDataProvider;


class StarRanking extends Common
{
    const RANKING_HOT = 'rk_hot'; //总榜
    const RANKING_JAPAN = 'rk_japan'; //日本女优榜
    const RANKING_MAINLAND = 'rk_mainland'; //大陆榜单
    const RANKING_TAIWAN = 'rk_taiwan'; //台湾榜单
    const RANKING_KOREA = 'rk_korea'; //韩国榜单
    const RANKING_HYBRID = 'rk_hybrid'; //混血榜单
    const RANKING_MODEL = 'rk_model'; //模特榜单
    const RANKING_BEAUTIFUL_GIRL = 'rk_girl'; //美少女榜单
    const RANKING_WEEK = 'rk_week';
    const RANKING_MONTH = 'rk_month';

    public static $rankTypes = ['rk_hot','rk_japan', 'rk_mainland','rk_taiwan','rk_korea','rk_hybrid','rk_model','rk_girl','rk_week','rk_month'];
    public static $rankTypeName = [
        'rk_hot' => '美女总排行榜',
        'rk_japan' => '日本女优榜单',
        'rk_mainland' => '大陆美女榜',
        'rk_taiwan' => '台湾美女榜',
        'rk_korea' => '韩国美女榜',
        'rk_hybrid' => '混血美女榜',
        'rk_model' => '美女模特榜',
        'rk_girl' => '美少女榜',
        'rk_week' => '美女周榜',
        'rk_month' => '美女月榜'
    ];

    private $rankType = '';
    private $currentPage = 1;
    private $pageSize = 10;
    private $returnFields = [];
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return '{{%star}}';
    }


    public function pageRanking($rankingType = '' , $currentPage = 1 , $pageSize = 10, $fields = []){
        if(!in_array($rankingType,static::$rankTypes)) return [];

        $this->rankType = $rankingType;
        $this->currentPage = $currentPage;
        $this->pageSize = $pageSize;
        $this->returnFields = empty($fields) ? $this->fields() : $fields;

        if($rankingType == StarRanking::RANKING_HOT){
            return Star::getMaxViewStar($currentPage,$pageSize,$fields);
        }

        if($rankingType == StarRanking::RANKING_WEEK){
            $this->weekRanking();
            return $this->pageRankingData();
        }

        if($rankingType == StarRanking::RANKING_MONTH){
            $this->rankType = 'starMonthView:'.date('Ym');
            return $this->pageRankingData();
        }

        if(!$this->isExistsRanking()) $this->setRankingRedis();

        return $this->pageRankingData();
    }


    /*
     * 分页获取排行榜的数据
     */
    private function pageRankingData(){
        $result = RedisService::pageData($this->rankType,$this->currentPage,$this->pageSize,'zSet');
        if(empty($result['data'])) return $result;

        $data = [];
        foreach ($result['data'] as $starId){
            $starInfo = Star::getStarInfoById($starId,$this->returnFields,false);
            if($starInfo){
                $starInfo['ranking'] = (int)Yii::$app->get('redis')->zrevrank($this->rankType,$starId) + 1;
                $data[] = $starInfo;
            }
        }
        $result['data'] = $data;

        return $result;
    }

    /*
     * 判断是否存在排行榜的缓存数据
     */
    private function isExistsRanking(){
        return (int)Yii::$app->get('redis')->exists($this->rankType) == 1 ? true : false;
    }

    /*
     * 设置排行榜的redis数据
     */
    private function setRankingRedis(){
        $starIds = $this->getStarIds();

        $redis = Yii::$app->get('redis');

        foreach ($starIds as $starId){
            $view = (int)Star::getStarInfoById($starId,['view'],false)['view'];
            $redis->zadd($this->rankType,$view,$starId);
        }
        $redis->expire($this->rankType,rand(20,24) * 60 * 60);
    }

    /*
     * 根据不同排行榜确定排行榜的ID集合
     */
    private function getStarIds(){
        if($this->rankType == StarRanking::RANKING_MAINLAND){
            $starIds = static::find()
                ->where(['like','country','中国'])
                ->andWhere(['not like','birth_place','台湾'])
                ->andWhere(['not like','birth_place','香港'])
                ->andWhere(['not like','birth_place','澳门'])
                ->select('id')
                ->asArray()
                ->all();
            $starIds = array_column($starIds,'id');
            return $starIds;
        }

        if($this->rankType == StarRanking::RANKING_JAPAN){
            $sql = 'SELECT id FROM {{%star}} WHERE `status` = 1 and `country` LIKE \'%日本%\'';
            $starIds = Yii::$app->db->createCommand($sql)->queryAll();
            return array_column($starIds,'id');
        }

        if($this->rankType == StarRanking::RANKING_TAIWAN){
            $sql = 'SELECT id FROM {{%star}} WHERE `status` = 1 and `birth_place` LIKE \'%台湾%\'';
            $starIds = Yii::$app->db->createCommand($sql)->queryAll();
            return array_column($starIds,'id');
        }

        if($this->rankType == StarRanking::RANKING_KOREA){
            $sql = 'SELECT id FROM {{%star}} WHERE `status` = 1 and `country` LIKE \'%韩国%\'';
            $starIds = Yii::$app->db->createCommand($sql)->queryAll();
            return array_column($starIds,'id');

        }

        if($this->rankType == StarRanking::RANKING_HYBRID){
            $sql = 'SELECT id FROM {{%star}} WHERE `status` = 1 and `desc` LIKE \'%混血%\'';
            $starIds = Yii::$app->db->createCommand($sql)->queryAll();
            return array_column($starIds,'id');
        }

        if($this->rankType == StarRanking::RANKING_MODEL){
            $sql = 'SELECT id FROM {{%star}} WHERE `status` = 1 and `desc` LIKE \'%模特%\'';
            $starIds = Yii::$app->db->createCommand($sql)->queryAll();
            return array_column($starIds,'id');
        }

        if($this->rankType == StarRanking::RANKING_BEAUTIFUL_GIRL){
            $sql = 'SELECT id FROM {{%star}} WHERE `status` = 1 and `desc` LIKE \'%美少女%\'';
            $starIds = Yii::$app->db->createCommand($sql)->queryAll();
            return array_column($starIds,'id');
        }

        return [];
    }



    /*
     * 美女周榜单数据 TODO删除过期数据
     */
    private function weekRanking(){
        $redisKeys = [
            date("Ymd",strtotime("-1 day")),
            date("Ymd",strtotime("-2 day")),
            date("Ymd",strtotime("-3 day")),
            date("Ymd",strtotime("-4 day")),
            date("Ymd",strtotime("-5 day")),
            date("Ymd",strtotime("-6 day")),
            date("Ymd",strtotime("-7 day")),
        ];
        $redisKeys = array_map(function($value){
            return 'starDayView:' . $value;
        },$redisKeys);

        //设置周榜数据过期的时间为每天 00:01:00
        $expireAt = strtotime(date('Y-m-d',strtotime("+1 day")).' 00:01:00');

        $destination = RedisService::zUnionStore($redisKeys,$expireAt - time());

        //如果最近7天都没有访问数据，随机返回一堆数据。但是应该不会存在这种情况。
        if(empty($destination)){
            $this->rankType = 'rk_weekRandomStars';

            //避免重复添加
            if($this->isExistsRanking()) return;

            $randomStars = Star::randomStars(100,['id','view']);
            foreach ($randomStars as $star){
                Yii::$app->get('redis')->zadd($this->rankType,intval($star['view'] * 0.8),$star['id']);
            }
            //过期时间设置为每天00:10：00过期
            Yii::$app->get('redis')->expireat($this->rankType,$expireAt);
        }else{
            $this->rankType = $destination;
            $count = Yii::$app->get('redis')->zcard($destination);
            if($count < 30){  //7天访问的数据太少 随机加一点
                $randomStars = Star::randomStars(100 - $count,['id','view']);
                foreach ($randomStars as $star){
                    Yii::$app->get('redis')->zadd($this->rankType,intval($star['view'] * 0.8),$star['id']);
                }
            }
        }
    }

}
